﻿#include "pch.h"

CEventManager::CEventManager()
{
    memset(this, 0, sizeof(CEventManager));
}

void CEventManager::printSelf(char *captionUpper, int32_t deep)
{
    char caption[1024];
    sprintf(caption, "%s:%s", captionUpper, "CEventManager");
    print4x(this, sizeof(CEventManager), caption);
    if (--deep >= 0)
    {
        if (this->pIParaWrapper)
        {
            this->pIParaWrapper->printSelf(caption, deep);
        }
        if (this->pTprgInfWrapper)
        {
            this->pTprgInfWrapper->printSelf(caption, deep);
        }
    }
    if (this->rawbagFreq)
    {
        sprintf(caption, "%s:%s", captionUpper, "CEventManager.rawbagFreq");
        print4x(this->rawbagFreq, sizeof(float), caption);
    }
    if (this->hsMin)
    {
        sprintf(caption, "%s:%s", captionUpper, "CEventManager.hsMin");
        print4x(this->hsMin, sizeof(int32_t), caption);
    }
}

// sub_10001AEA
CEventManager *CEventManager::init(CIParaWrapper *pIPara, CTprgInfWrapper *pTprgInf, float *rawbagFreq)
{
    this->pIParaWrapper = pIPara;
    this->pTprgInfWrapper = pTprgInf;
    this->rawbagFreq = rawbagFreq;
    this->init_();
    return this;
};

// sub_10001B1C
CEventManager *CEventManager::init_()
{
    float tdouble;
    float normalizeSlope;
    //// sub_10019820(*(void **)this, **(float **)(this + 8));
    //// 这里存疑问 **(float **)(this + 8))   ==> this->rawbagFreq
    //// float TRAWBAG.freq 难道是 float* TRAWBAG.freq ??? 数据来源参考 sub_1001B1A0
    this->pIParaWrapper->validateWidthAndPkWidth(*this->rawbagFreq);
    this->pIParaWrapper->validateSlopeAndpkNoise();
    this->pIParaWrapper->validateWidthAndPkDrift(*this->rawbagFreq);
    this->rawbagFreqD10 = (int32_t)(*this->rawbagFreq / 10.0);
    if (this->rawbagFreqD10 < 2)
    {
        this->rawbagFreqD10 = 2;
    }
    if (this->pIParaWrapper->getSlope() >= 0.001)
    {
        this->eventWidth = this->pIParaWrapper->getWidth();
    }
    else
    {
        this->eventWidth = 0;
    }
    if (!this->eventWidth)
    {
        this->eventWidth = this->rawbagFreqD10;
    }
    this->width0 = this->eventWidth;
    this->eventSlope = (float)this->pIParaWrapper->getSlope();
    if (this->eventSlope >= 0.001)
    {
        normalizeSlope = this->eventSlope / this->eventWidth;
    }
    else
    {
        this->eventSlope = 0;
        normalizeSlope = 0.0;
    }
    this->normalizeSlope = normalizeSlope;
    this->eventDrift = (float)this->pIParaWrapper->getDrift();
    this->wdMode = this->pIParaWrapper->getWdMode();
    tdouble = (float)this->pIParaWrapper->getTdouble();
    this->tdoubleCount = this->getVibrateCount(tdouble);
    this->minHeight = this->pIParaWrapper->getMinHeight();
    this->minArea = this->pIParaWrapper->getMinArea();
    this->tailMode = this->pIParaWrapper->getTailMode();
    this->autoNegative = this->pIParaWrapper->getAutoNegative();
    this->shouldSens = this->pIParaWrapper->getShouldSens();
    this->iParaCalcCounter = 1;
    this->buffer0Time = 0;
    this->drift0 = (float)this->rawbagFreqD10;
    this->avgDiffHeight = 0;
    this->slope0 = 0;
    this->x19 = 0;
    this->absDiffHeight = 0;
    this->accDiffHeight = 0;
    this->x24 = 0;
    this->autoNegative0 = false;
    this->pIParaWrapper->validateWidthAndPkWidth(*this->rawbagFreq);
    this->pIParaWrapper->validateSlopeAndpkNoise();
    this->pIParaWrapper->validateWidthAndPkDrift(*this->rawbagFreq);
    return this->clear();
};

// sub_10019B00
CEventManager *CEventManager::clear()
{
    memset(this->evType, 0, 0x80u);
    memset(this->evCount, 0, 0x80u);
    memset(this->evPara, 0, 0x80u);
    this->x122 = 0;
    this->topOrBottom = false; // x123
    this->x124 = 0;
    this->hsMin = NULL;
    this->rawbagIdx = 0;
    this->rawbagVal = 0;
    return this;
};

// sub_10019BB0
int32_t CEventManager::getVibrateCount(float time)
{
    return (int32_t)(time * (*this->rawbagFreq * 60.0));
};

// sub_1001A840
float CEventManager::getNormalizeSlope()
{
    return this->normalizeSlope;
};

// sub_1001A860
float CEventManager::getSlope()
{
    return this->eventSlope;
};

// sub_1001AA00
double CEventManager::getRawbagFreqValue()
{
    return *this->rawbagFreq;
};

// sub_1001A1C0
int32_t CEventManager::getSlopeX10()
{
    return (int32_t)(this->eventSlope * 10.0);
};

// sub_1001A9B0
double CEventManager::getEventDrift()
{
    return this->eventDrift;
};

// sub_10001D64
int32_t CEventManager::checkStop(int32_t checkTime)
{
    float stopTime;
    int32_t ret = false;

    if (this->pIParaWrapper->getStopTime() > 0.001)
    {
        stopTime = (float)this->pIParaWrapper->getStopTime();
        if (checkTime >= this->getVibrateCount(stopTime))
        {
            ret = true;
        }
    }
    return ret;
};

// sub_100023A6
int32_t CEventManager::setEventData(int32_t counter)
{
    float normSlope;
    PKWD_MODE mode;
    if (this->evType[PARA_WIDTH] && this->evPara[PARA_WIDTH] > 0.0)
    {
        this->eventWidth = this->divideX10_3(this->evPara[PARA_WIDTH]);
    }
    else
    {
        mode = this->pIParaWrapper->getWdMode();
        if (mode == WD_TDOUBLE)
        {
            this->eventWidth = (int32_t)this->enlargeWidth0(counter);
        }
        else if (mode == WD_AUTO)
        {
            this->eventWidth = this->width0;
        }
    }
    if (this->evType[PARA_NOISE] && this->evPara[PARA_NOISE] > 0.0)
    {
        if (this->evType[PARA_NOISE] == 1)
        {
            gSlope = (int32_t)this->eventSlope;
            this->eventSlope = (float)divideX10(this->evPara[PARA_NOISE]);
            if (this->eventSlope >= 0.001)
            {
                normSlope = this->eventSlope / this->eventWidth;
            }
            else
            {
                this->eventSlope = 0;
                normSlope = 0.0;
            }
            this->normalizeSlope = normSlope;
        }
        else if (this->evType[PARA_NOISE] == 2)
        {
            this->eventSlope = (float)gSlope;
            if (this->eventSlope >= 0.001)
            {
                normSlope = this->eventSlope / this->eventWidth;
            }
            else
            {
                this->eventSlope = 0;
                normSlope = 0.0;
            }
            this->normalizeSlope = normSlope;
        }
    }
    if (this->evType[PARA_DRIFT] && this->evPara[PARA_DRIFT] > 0.0)
    {
        if (this->evType[PARA_DRIFT] == 1)
        {
            gDrift = (int32_t)this->eventDrift;
            this->eventDrift = (float)this->divideFreq(this->evPara[PARA_DRIFT]);
        }
        else if (this->evType[PARA_DRIFT] == 2)
        {
            this->eventDrift = (float)gDrift;
        }
    }
    return true;
};

// sub_10019FF0
int32_t CEventManager::divideX10_3(float val)
{
    int32_t result;

    result = (int32_t)(val * 10.0 * *this->rawbagFreq / 3.0 + 0.5);
    if (!result)
    {
        result = 1;
    }
    return result;
};

// sub_1000232B
double CEventManager::enlargeWidth0(int32_t counter)
{
    float fraction;
    float validFraction;

    if (this->buffer0Time <= this->tdoubleCount)
    {
        fraction = 0.0;
    }
    else
    {
        fraction = (float)((double)(counter - this->buffer0Time) / (double)(this->tdoubleCount - this->buffer0Time));
    }
    validFraction = fraction;
    if (fraction < 0.0)
    {
        validFraction = 0.0;
    }
    return (double)((validFraction + 1.0) * (double)(int32_t)this->width0);
};

// sub_1001A060
double CEventManager::divideFreq(float val)
{
    return val / *this->rawbagFreq;
};

// sub_100025A3
int32_t CEventManager::setEventTypes(int32_t vibraCount)
{
    int32_t i;
    int32_t event;

    if (!this->pTprgInfWrapper->eCount)
    {
        return false;
    }
    for (i = 0; i < 32; ++i)
    {
        if (this->evCount[i] > 0)
        {
            if (vibraCount >= this->evCount[i])
            {
                if (vibraCount == this->evCount[i])
                {
                    this->evType[i] = 2;
                }
                else
                {
                    this->evType[i] = 0;
                    if (i != 9)
                    {
                        this->evCount[i] = 0;
                    }
                    memset((void *)&this->evPara[i], 0, 4u);
                }
            }
            else
            {
                this->evType[i] = 3;
            }
        }
    }
    TDLLTPRGListItem *pPRG = (TDLLTPRGListItem *)this->pTprgInfWrapper->head;
    if (this->x122 < this->pTprgInfWrapper->eCount && (int32_t)this->getVibrateCount(pPRG[this->x122].ts) == vibraCount)
    {
        event = pPRG[this->x122].event;
        this->evType[event] = 1;
        this->evCount[event] = this->getVibrateCount(pPRG[this->x122].te);
        if (!this->evCount[event])
        {
            this->evCount[event] = -1;
        }
        while (1)
        {
            memcpy((void *)&this->evPara[event], &pPRG[this->x122].paraValue, 4u);
            if (++this->x122 >= this->pTprgInfWrapper->eCount || (int32_t)this->getVibrateCount(pPRG[this->x122].ts) != vibraCount)
            {
                break;
            }
            event = pPRG[this->x122].event;
            this->evType[event] = 1;
            this->evCount[event] = this->getVibrateCount(pPRG[this->x122].te);
            if (!this->evCount[event])
            {
                this->evCount[event] = -1;
            }
        }
    }
    return true;
};

// sub_10001DB8
int32_t CEventManager::testParaCalcCounter()
{
    if (this->iParaCalcCounter <= 0 || this->iParaCalcCounter >= 5)
    {
        return 1;
    }
    ++this->iParaCalcCounter;
    return 0;
};

// sub_1001B680
int32_t CEventManager::isSlopeNearZero()
{
    return this->pIParaWrapper->getSlope() < 0.001 && this->iParaCalcCounter > 0;
};

// sub_10001DED
int32_t CEventManager::setIParaValues(CBuffer10Wrapper *pBuffer10Wrapper)
{
    int32_t i;
    int32_t buff0Time;
    int32_t testPkNoise;
    float initTime;
    float testPkWidth;
    float testPkDrift;
    float avgDiffHeight;
    float absDiffHeight;
    int32_t diffSlope;
    int32_t result;

    result = false;
    if (this->iParaCalcCounter == 5)
    {
        gBufHeight = (int32_t)pBuffer10Wrapper->getBuffer10Height(0);
        gParaCalcCounter = 0;
        for (i = 0; i < 4; ++i)
        {
            absDiffHeight = (float)fabs(pBuffer10Wrapper->getBuffer10DiffHeight(i, i + 1));
            if (absDiffHeight < 10.0)
            {
                if (absDiffHeight <= this->absDiffHeight)
                {
                    ;
                }
                else
                {
                    this->absDiffHeight = absDiffHeight;
                }
                this->accDiffHeight = absDiffHeight + this->accDiffHeight;
                ++gParaCalcCounter;
            }
        }
    }
    else
    {
        absDiffHeight = (float)fabs(pBuffer10Wrapper->getBuffer10DiffHeight(4, 5));
        if (absDiffHeight <= (double)this->absDiffHeight)
        {
            ;
        }
        else
        {
            this->absDiffHeight = absDiffHeight;
        }
        this->accDiffHeight = absDiffHeight + this->accDiffHeight;
        ++gParaCalcCounter;
    }
    ++this->iParaCalcCounter;
    if (this->absDiffHeight < 1.0)
    {
        this->absDiffHeight = 1.0; // int32_t 1065353216 --> float 1.0
    }
    this->eventSlope = this->absDiffHeight;
    if (gParaCalcCounter)
    {
        avgDiffHeight = (float)(this->accDiffHeight / (double)gParaCalcCounter);
    }
    else
    {
        avgDiffHeight = 0.0;
    }
    if (avgDiffHeight < 0.1)
    {
        avgDiffHeight = (float)0.1;
    }
    diffSlope = (int32_t)(this->eventSlope / avgDiffHeight + 0.5);
    if (diffSlope < 1)
    {
        diffSlope = 1;
    }
    if (this->eventWidth < diffSlope + 1)
    {
        this->eventWidth = diffSlope + 1;
    }
    if (this->eventWidth > this->width0)
    {
        if (this->eventWidth > 2 * this->width0)
        {
            this->eventWidth = 2 * this->width0;
        }
    }
    else
    {
        this->eventWidth = this->width0;
    }
    this->normalizeSlope =
        (float)(((double)diffSlope * avgDiffHeight + this->absDiffHeight) / (double)(diffSlope + 1));
    if (gParaCalcCounter > 0)
    {
        buff0Time = pBuffer10Wrapper->getBuffer10Time(0);
        initTime = this->pIParaWrapper->getIParaInitTime();
        if (buff0Time > (int32_t)this->getVibrateCount(initTime) && (pBuffer10Wrapper->hasSalientPoint(this->normalizeSlope) || (this->autoNegative && pBuffer10Wrapper->hasSalientPointType2(this->normalizeSlope))))
        {
            this->buffer0Time = pBuffer10Wrapper->getBuffer10Time(0);
            this->eventWidth = this->width0;
            this->drift0 = (float)this->eventWidth;
            this->slope0 = this->eventSlope;
            this->avgDiffHeight = (int32_t)(this->slope0 / (double)diffSlope);
            this->x19 = 0;
            testPkWidth = (float)divideX3_10(this->drift0, *this->rawbagFreq);
            this->pIParaWrapper->setTestPkWidth(testPkWidth);
            testPkNoise = (int32_t)multiplyX10(this->slope0);
            this->pIParaWrapper->setTestPkNoise(testPkNoise);
            testPkDrift = (float)(multiplyX((float)this->x19, *this->rawbagFreq));
            this->pIParaWrapper->setTestPkDrift(testPkDrift);
            if (this->autoNegative && pBuffer10Wrapper->hasSalientPointType2(this->normalizeSlope))
            {
                this->autoNegative0 = true;
            }
            if (this->pIParaWrapper->getSlope() >= 0.001)
            {
                this->eventSlope = (float)this->pIParaWrapper->getSlope();
                this->normalizeSlope = (float)(this->eventSlope / (double)diffSlope);
            }
            else
            {
                this->pIParaWrapper->setSlope(this->eventSlope);
                this->pIParaWrapper->validateSlopeAndpkNoise();
                this->normalizeSlope = (float)(this->eventSlope / (double)diffSlope);
                result = true;
            }
            if (this->pIParaWrapper->getWidth())
            {
                this->eventWidth = this->pIParaWrapper->getWidth();
                this->rawbagFreqD10 = this->eventWidth;
                this->width0 = this->rawbagFreqD10;
            }
            else
            {
                this->pIParaWrapper->setWidth(this->eventWidth);
                this->pIParaWrapper->validateWidthAndPkWidth(*this->rawbagFreq);
                this->rawbagFreqD10 = this->eventWidth;
                this->width0 = this->rawbagFreqD10;
                result = true;
            }
            if (this->pIParaWrapper->getDrift() == 0.0)
            {
                this->eventDrift = (float)this->x19;
                this->pIParaWrapper->setDrift(this->eventDrift);
            }
            else
            {
                this->eventDrift = (float)this->pIParaWrapper->getDrift();
            }
            this->absDiffHeight = 0;
            this->accDiffHeight = 0;
            this->iParaCalcCounter = 0;
            gBufHeight = 0;
        }
    }
    return result;
};

// sub_1001B6C0
int32_t CEventManager::turnOffAutoNegative()
{
    if (!this->autoNegative0)
    {
        return false;
    }
    this->autoNegative0 = false;
    return true;
};

// sub_1001B710
CEventManager *CEventManager::setWidth(int32_t width)
{
    this->eventWidth = width;
    return this;
};

// sub_1001B6F0
CEventManager *CEventManager::setWidth0(int32_t width0)
{
    this->width0 = width0;
    return this;
};

// sub_1000289C
int32_t CEventManager::checkPrgItemEven(int32_t timeEnd, int32_t event, int32_t *count, int32_t flag)
{
    float te;
    int32_t result;
    float ts;
    int32_t vCountEnd;
    int32_t i;
    int32_t vCountStart;
    result = 0;

    for (i = 0; i < this->pTprgInfWrapper->eCount; ++i)
    {
        if (this->pTprgInfWrapper->getPrgItemEventAndTsTe(i, &ts, &te) == event)
        {
            vCountStart = this->getVibrateCount(ts);
            vCountEnd = this->getVibrateCount(te);
            if (timeEnd >= vCountStart && timeEnd <= vCountEnd + 1)
            {
                if (timeEnd == vCountStart)
                {
                    result = 1;
                    if (count)
                    {
                        *count = vCountEnd;
                    }
                }
                else if (timeEnd == vCountEnd + 1)
                {
                    result = 2;
                    if (count && flag)
                    {
                        *count = 0;
                    }
                }
                else
                {
                    result = 3;
                }
                return result;
            }
        }
    }
    return result;
};

// sub_100022E3
int32_t CEventManager::calcWidth0(int32_t val)
{
    int32_t result = val;
    if (val > 0)
    {
        if (val <= 25 * this->rawbagFreqD10)
        {
            result = this->rawbagFreqD10;
        }
        else
        {
            result = (val + 10) / 25;
        }
        this->width0 = result;
    }
    return result;
}
